//Code for interfacing with the MAX181 in I/O 12-bit mode
//All code written by Nick Contini
//Last updated 2/27/2014

//Value of the sample with 4 zeros trailing. In bipolar mode bits are outputted in
//two's compliment format, so it must be of type int. If not using bipolar
//mode make this unsigned.
int sample;

//8 most significant bits
byte MSB;

//4 least significant bits with 4 zeros trailing
byte LSB;

//keeps track of the number of samples taken
int numSamples;

void setup()
{
  //there have been no samples taken yet
  numSamples = 0;
  
  //No operation command in assembly. Lasts 62.5 nanoseconds since the arduino clocks at 16MHz
  #define NOP __asm__ __volatile__ ("nop\n\t")
  
  //initialize serial communication to transfer at 115200 bps
  Serial.begin(115200); 
  
  
  //Ports were based on ATmega2560, will vary between arduino models
  //input port for 8 MSB
  DDRA=B00000000;
  
  //input port for 4 LSB and the output port for 3 address bits
  DDRL=B00000111;
  
  //output for CS, WR, RD (all active low) and input for BUSY (also active low)
  DDRD=B00001110;
  
  //Does a read operation to power up "clean"
  PORTD = B00000100;
  NOP;
  NOP;
  NOP;
  PORTD = B00001110;
  
  //AIN0 as input
  #define SIGN0 B00000000
  
  //AIN1 as input
  #define SIGN1 B00000001
  
  //AIN2 as input
  #define SIGN2 B00000010
  
  //and so on if you wanted to add extra signals. Up to 6 signals
}

//acts as the conversion cycle
void cycle(){
  
  //WR and CS low
  PORTD=B00000010;
  
  //keep the pulse low for the appropriate time (at least 120 ns)
  NOP;
  NOP;
  
  //WR and CS high, BUSY is now low
  PORTD=B00001110;
  
  //do nothing until the ADC is not busy
  while(digitalRead(21)==LOW){}
  
  //RD and CS low
  PORTD=B00000100;
  
  //wait for ADC to output digital bits (avaible after max 150 ns after RD set low)
  NOP;
  NOP;
  
  //8 MSB
  MSB=PINA;
  
  //puts the 8MSB and the 4 LSB and 4 0s into a word
  sample=word(MSB,PINL);
  
  //RD and CS high. End of sampling cycle
  PORTD=B00001110;
}

void loop()
{
  //here purely to limit the number of samples taken.
  //can be taken out to continuously take samples.
  if(numSamples!=20){
    
    //sets adress to AIN0
    PORTL=SIGN0;
    cycle();
  
    //shift sample to the right 4. Convert to voltage and send to serial monitor.
    //since peak to peak voltage is 5V and there are 12 bits, the quantization levels
    //are spaced 5/(2^12-1) which is about .001221V.
    Serial.print(((float)(sample>>4))*.001221);
    Serial.print(" ");
    
    //switch to AIN1
    PORTL=SIGN1;
    cycle();
      
    Serial.print(((float)(sample>>4))*.001221);
    Serial.print(" ");
    
    //Switch to AIN2
    PORTL=SIGN2;
    cycle();
  
    Serial.println(((float)(sample>>4))*.001221);
    
    //output is sorted into columns by signal
  
    //increment number of samples taken
    numSamples++;
  }
}
